<?php
namespace ZyucMini;

require_once __DIR__ . '/Function.php';
require_once __DIR__ . '/Core/Autoload.php';

use ZyucMini\Core\Autoload;
use ZyucMini\Core\Config;
use ZyucMini\Core\Dir;
use ZyucMini\Core\File;
use ZyucMini\Core\Error;
use ZyucMini\Core\Logger;
use ZyucMini\Core\DatabaseManager;

/**
 * 主程序类
 */
class Main
{

    // 应用容器
    private static $appContainer = [];
    // mainError
    private static $mainError = null;
    // mainAutoload
    private static $mainAutoload = null;
    
    // 框架初始化状态
    private static $initialized = false;
    
    // 应用状态管理
    private static $appStatus = [];
    
    // 应用状态常量
    const APP_STATUS_LOADING = 'loading';
    const APP_STATUS_LOADED = 'loaded';
    const APP_STATUS_RUNNING = 'running';
    const APP_STATUS_STOPPED = 'stopped';
    const APP_STATUS_ERROR = 'error';

    // 初始化框架
    public static function init()
    {
        // 检查是否已经初始化
        if (self::$initialized) {
            return;
        }

        // 设置时区
        date_default_timezone_set('Asia/Shanghai');
        
        self::autoload();
        self::initErrorHandling();
        
        // 标记为已初始化
        self::$initialized = true;
    }

    private static function autoload()
    {
        // 初始化自动加载
        self::$mainAutoload = new Autoload();
        self::$mainAutoload->addNamespace('ZyucMini\\Core', __DIR__ . '/Core');
        self::$mainAutoload->addNamespace('ZyucMini\\Components', __DIR__ . '/Components');
        self::$mainAutoload->register();
    }

    private static function initErrorHandling()
    {
        // 初始化错误处理
        self::$mainError = new Error();
        self::$mainError->init();
    }

    public static function runApp(array $config = [])
    {
        echo "Main class is running.\n";
    }

    public static function loadApp($appPath)
    {
        // 加载应用配置
        $config_dir = $appPath . '/config';
        if (!Dir::exists($config_dir)) {
            throw new \Exception("ZyucMini\Main Error: config directory not found: $config_dir");
        }

        // app配置
        $app_config_file = $config_dir . '/app.php';
        if (!File::exists($app_config_file)) {
            throw new \Exception("ZyucMini\Main Error: app config file not found: $app_config_file");
        }
        $app_conf = [];
        $app_conf['app'] = require_once $app_config_file;

        // 验证应用配置
        self::validateAppConfig($app_conf['app'], $appPath, $app_config_file);

        // 加载应用命名空间（直接整个目录）
        $appNamespace = $app_conf['app']['namespace'];
        self::$mainAutoload->addNamespace($appNamespace, $appPath);

        // 加载应用自动加载配置
        if (zyucmini_get($app_conf['app'], 'autoload')) {
            $autoload_config = $app_conf['app']['autoload'];
            foreach ($autoload_config as $namespace => $path) {
                self::$mainAutoload->addNamespace($namespace, $path);
            }
        }

        // 加载日志配置
        if (zyucmini_get($app_conf['app'], 'log_dir')) {

            $log_dir = $app_conf['app']['log_dir'];
            // ruzhg 目录存在
            $app_conf['logger'] = new Logger($log_dir);
            
        }

        // 错误信息
        if (zyucmini_get($app_conf['app'], 'error_log')) {
            // 设置错误日志路径
            $error_log = $app_conf['app']['error_log'];
            self::$mainError->setLogPath($error_log);
        }

        // 加载数据库配置
        if (zyucmini_get($app_conf['app'], 'db')) {
            $db_config = $app_conf['app']['db'];
            foreach ($db_config as $key => $conf) {
                if (!isset($conf['type'])) {
                    throw new \Exception("ZyucMini\Main Error: db config 'type' not set for connection '$key' in: $app_config_file");
                }
                // 使用连接管理器注册数据库连接配置，实现连接复用
                DatabaseManager::registerConnection($key, $conf);
            }
        }

        // 加载路由配置
        $app_route_file = $config_dir . '/route.php';
        if (File::exists($app_route_file)){
            $app_conf['route'] = require_once $app_route_file;
        }
        // 缓存命名空间
        Config::set($appNamespace, $app_conf);

        // 根据debug配置决定是否输出调试信息
        if (zyucmini_get($app_conf['app'], 'debug', false)) {
            echo "缓存命名空间: $appNamespace\n";
        }

        self::$appContainer[$appPath] = $app_conf;
        
        // 设置应用状态为已加载
        self::setAppStatus($appPath, self::APP_STATUS_LOADED);
    }

    public static function getApp($appPath)
    {
        return self::$appContainer[$appPath] ?? null;
    }
    
    /**
     * 启动应用
     * 
     * @param string $appPath 应用路径
     * @throws \Exception
     */
    public static function startApp($appPath)
    {
        // 确保框架已初始化
        if (!self::$initialized) {
            throw new \Exception("ZyucMini\Main Error: Framework not initialized. Call Main::init() first.");
        }
        
        try {
            self::setAppStatus($appPath, self::APP_STATUS_LOADING);
            self::loadApp($appPath);
            self::setAppStatus($appPath, self::APP_STATUS_RUNNING);
        } catch (\Exception $e) {
            self::setAppStatus($appPath, self::APP_STATUS_ERROR);
            throw $e;
        }
    }
    
    /**
     * 停止应用
     * 
     * @param string $appPath 应用路径
     */
    public static function stopApp($appPath)
    {
        // 关闭应用相关的数据库连接
        self::closeAppConnections($appPath);
        
        // 清理应用缓存（如果有的话）
        self::clearAppCache($appPath);
        
        // 设置应用状态为已停止
        self::setAppStatus($appPath, self::APP_STATUS_STOPPED);
        
        // 从应用容器中移除
        unset(self::$appContainer[$appPath]);
    }
    
    /**
     * 重启应用
     * 
     * @param string $appPath 应用路径
     * @throws \Exception
     */
    public static function restartApp($appPath)
    {
        $currentStatus = self::getAppStatus($appPath);
        
        if ($currentStatus && $currentStatus['status'] === self::APP_STATUS_RUNNING) {
            self::stopApp($appPath);
        }
        
        self::startApp($appPath);
    }
    
    /**
     * 关闭应用相关的数据库连接
     * 
     * @param string $appPath
     */
    public static function closeAppConnections($appPath)
    {
        $app_conf = self::getApp($appPath);
        if ($app_conf && isset($app_conf['app']['db'])) {
            foreach (array_keys($app_conf['app']['db']) as $connectionName) {
                DatabaseManager::closeConnection($connectionName);
            }
        }
    }
    
    /**
     * 获取应用数据库连接状态
     * 
     * @param string $appPath
     * @return array
     */
    public static function getAppConnectionsStatus($appPath)
    {
        $app_conf = self::getApp($appPath);
        if ($app_conf && isset($app_conf['app']['db'])) {
            $status = [];
            foreach (array_keys($app_conf['app']['db']) as $connectionName) {
                if (DatabaseManager::hasConnection($connectionName)) {
                    $status[$connectionName] = DatabaseManager::getConnection($connectionName)->getConfig();
                }
            }
            return $status;
        }
        return [];
    }
    
    /**
     * 获取所有数据库连接状态
     * 
     * @return array
     */
    public static function getAllConnectionsStatus()
    {
        return DatabaseManager::getConnectionsStatus();
    }

    /**
     * 以路由的方式启动
     */
    public static function routeStart($appPath)
    {
        // 确保框架已初始化
        if (!self::$initialized) {
            throw new \Exception("ZyucMini\Main Error: Framework not initialized. Call Main::init() first.");
        }
        
        self::startApp($appPath);
        
        // 检查路由是否存在
        if (!zyucmini_get(self::$appContainer[$appPath], 'route')) {
            throw new \Exception("ZyucMini\Main Error: route not defined in app: $appPath");
        }

        self::$appContainer[$appPath]['route']->dispatch();
    }

    /**
     * 设置应用状态
     * 
     * @param string $appPath 应用路径
     * @param string $status 状态
     */
    public static function setAppStatus($appPath, $status)
    {
        self::$appStatus[$appPath] = [
            'status' => $status,
            'timestamp' => time(),
            'datetime' => date('Y-m-d H:i:s')
        ];
    }
    
    /**
     * 获取应用状态
     * 
     * @param string $appPath 应用路径
     * @return array|null
     */
    public static function getAppStatus($appPath)
    {
        return self::$appStatus[$appPath] ?? null;
    }
    
    /**
     * 获取应用健康状态
     * 
     * @param string $appPath 应用路径
     * @return array
     */
    public static function getAppHealth($appPath)
    {
        $status = self::getAppStatus($appPath);
        $connections = self::getAppConnectionsStatus($appPath);
        
        return [
            'app_path' => $appPath,
            'status' => $status,
            'connections' => count($connections),
            'memory_usage' => memory_get_usage(true),
            'memory_peak' => memory_get_peak_usage(true),
            'uptime' => $status ? (time() - $status['timestamp']) : 0
        ];
    }
    
    /**
     * 获取所有应用状态
     * 
     * @return array
     */
    public static function getAllAppsStatus()
    {
        $status = [];
        foreach (self::$appStatus as $appPath => $appStatus) {
            $status[$appPath] = self::getAppHealth($appPath);
        }
        return $status;
    }
    
    /**
     * 检查框架是否已初始化
     * 
     * @return bool
     */
    public static function isInitialized()
    {
        return self::$initialized;
    }
    
    /**
     * 重置框架状态（主要用于测试）
     */
    public static function reset()
    {
        self::$initialized = false;
        self::$appContainer = [];
        self::$appStatus = [];
        self::$mainError = null;
        self::$mainAutoload = null;
        
        // 关闭所有数据库连接
        DatabaseManager::closeAllConnections();
        DatabaseManager::clearConfigCache();
        
        // 清理配置
        Config::clear();
    }
    
    /**
     * 清理应用缓存
     * 
     * @param string $appPath 应用路径
     */
    private static function clearAppCache($appPath)
    {
        // 这里可以添加应用特定的缓存清理逻辑
        // 例如：清理配置缓存、路由缓存等
        $appNamespace = self::$appContainer[$appPath]['app']['namespace'] ?? null;
        if ($appNamespace) {
            Config::remove($appNamespace);
        }
    }

    /**
     * 验证应用配置
     * 
     * @param array $appConfig 应用配置
     * @param string $appPath 应用路径
     * @param string $configFile 配置文件路径
     * @throws \Exception
     */
    private static function validateAppConfig($appConfig, $appPath, $configFile)
    {
        // 验证配置是否为数组
        if (!is_array($appConfig)) {
            throw new \Exception("ZyucMini\Main Error: app config must return an array in: $configFile");
        }
        
        // 验证必需的配置项
        $required = ['namespace'];
        foreach ($required as $key) {
            if (!isset($appConfig[$key])) {
                throw new \Exception("ZyucMini\Main Error: app config '$key' not set in: $configFile");
            }
        }
        
        // 验证命名空间格式
        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_\\\\]*$/', $appConfig['namespace'])) {
            throw new \Exception("ZyucMini\Main Error: invalid namespace format '{$appConfig['namespace']}' in: $configFile");
        }
        
        // 验证数据库配置（如果存在）
        if (isset($appConfig['db']) && is_array($appConfig['db'])) {
            foreach ($appConfig['db'] as $key => $dbConfig) {
                if (!is_array($dbConfig)) {
                    throw new \Exception("ZyucMini\Main Error: db config for '$key' must be an array in: $configFile");
                }
                
                if (!isset($dbConfig['type'])) {
                    throw new \Exception("ZyucMini\Main Error: db config 'type' not set for connection '$key' in: $configFile");
                }

                // 验证数据库类型
                $supportedTypes = ['mysql', 'sqlite', 'pgsql'];
                if (!in_array($dbConfig['type'], $supportedTypes)) {
                    throw new \Exception("ZyucMini\Main Error: unsupported database type '{$dbConfig['type']}' for connection '$key' in: $configFile");
                }
            }
        }
        
        // 验证日志配置（如果存在）
        if (isset($appConfig['log_dir']) && !is_string($appConfig['log_dir'])) {
            throw new \Exception("ZyucMini\Main Error: log_dir must be a string in: $configFile");
        }
        
        // 验证错误日志配置（如果存在）
        if (isset($appConfig['error_log']) && !is_string($appConfig['error_log'])) {
            throw new \Exception("ZyucMini\Main Error: error_log must be a string in: $configFile");
        }
    }
}
